﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Craps
{
    
    public class CrapsSystem
    {
        public enum Bet { passline, passlineodds, dontpass, 
            dontpassodds, come, four, five, six, eight, nine, ten,
            field, pocket};

        private int point;
        private Dictionary<Bet, uint> bets;
        private Dictionary<Bet, uint> oldBets;

        public CrapsSystem()
        {
            bets = new Dictionary<Bet, uint>();
            oldBets = new Dictionary<Bet, uint>();
            point = 0;
        }

        private void win(Bet bet, int number)
        {
            if (bets.ContainsKey(bet))
            {
                uint betvalue = bets[bet];
                switch (bet)
                {
                    case Bet.passline:
                        bets[bet] *= 2;
                        break;
                    case Bet.passlineodds:
                        if (number == 4 || number == 10)
                        {
                            // 2 to 1
                            bets[bet] += betvalue * 2;
                        }
                        else if (number == 5 || number == 9)
                        {
                            // 3 to 2
                            bets[bet] += betvalue * 3 / 2;
                        }
                        else if (number == 6 || number == 8)
                        {
                            bets[bet] += betvalue * 6 / 5;
                        }
                        movetopocket(bet);
                        break;
                    case Bet.come:
                        bets[bet] *= 2;
                        break;
                    case Bet.four:
                    case Bet.ten:
                        bets[bet] *= 3;
                        break;
                    case Bet.five:
                    case Bet.nine:
                        bets[bet] += betvalue * 3 / 2;
                        break;
                    case Bet.six:
                    case Bet.eight:
                        bets[bet] += betvalue * 6 / 5;
                        break;
                }
            }
        }

        private void movetopocket(Bet bet)
        {
            movebet(bet, Bet.pocket);
        }

        private void movebet(Bet from, Bet to)
        {
            if (bets.ContainsKey(from))
            {
                if (bets.ContainsKey(to))
                {
                    bets[to] += bets[from];
                }
                else
                {
                    bets[to] = bets[from];
                }
                bets.Remove(from);
            }
        }
        private void lose(Bet bet)
        {
            if (bets.ContainsKey(bet))
            {
                bets.Remove(bet);
            }
        }

        public int getPoint()
        {
            return point;
        }

        public Dictionary<Bet, uint> getBets()
        {
            return new Dictionary<Bet,uint>(bets);
        }

        public Dictionary<Bet, uint> getOldBets()
        {
            return new Dictionary<Bet,uint>(oldBets);
        }

        public bool haveBets()
        {
            return bets.Count > 0;
        }

        public Dictionary<Bet, uint> handleRoll(int die1, int die2)
        {
            oldBets = new Dictionary<Bet, uint>(bets);
            int roll = die1 + die2;
            int oldpoint = point;
            if (point == 0)
            {
                if (roll == 7 || roll == 11)
                {
                    // pass line wins, don't pass loses
                    win(Bet.passline, roll);
                    lose(Bet.dontpass);
                }
                else if (roll == 4 || roll == 5 || roll == 6 || roll == 8 || roll == 9 || roll == 10)
                {
                    point = roll;
                }
                else if (roll == 3 || roll == 2 || roll == 12)
                {
                    lose(Bet.passline);
                }
            }
            else
            {
                if (roll == 7)
                {
                    // Everything loses
                    lose(Bet.passline);
                    lose(Bet.passlineodds);
                    lose(Bet.four);
                    lose(Bet.five);
                    lose(Bet.six);
                    lose(Bet.eight);
                    lose(Bet.nine);
                    lose(Bet.ten);
                    point = 0;

                    // Except the don't pass and come bets
                    win(Bet.come, roll);
                    win(Bet.dontpass, roll);
                    win(Bet.dontpassodds, roll);
                }
                else if (roll == point)
                {
                    win(Bet.passline, roll);
                    win(Bet.passlineodds, roll);

                    lose(Bet.dontpass);
                    lose(Bet.dontpassodds);

                    point = 0;
                }

                // TODO: Come bet moving / odds
                switch (roll)
                {
                    case 2:
                        win(Bet.field, roll);
                        lose(Bet.come);
                        break;
                    case 3:
                        win(Bet.field, roll);
                        lose(Bet.come);
                        break;
                    case 4:
                        win(Bet.field, roll);
                        win(Bet.four, roll);
                        movebet(Bet.come, Bet.four);
                        break;
                    case 5:
                        win(Bet.five, roll);
                        movebet(Bet.come, Bet.five);
                        break;
                    case 6:
                        win(Bet.six, roll);
                        movebet(Bet.come, Bet.six);
                        break;
                    case 8:
                        win(Bet.eight, roll);
                        movebet(Bet.come, Bet.eight);
                        break;
                    case 9:
                        win(Bet.nine, roll);
                        win(Bet.field, roll);
                        movebet(Bet.come, Bet.nine);
                        break;
                    case 10:
                        win(Bet.ten, roll);
                        win(Bet.field, roll);
                        movebet(Bet.come, Bet.ten);
                        break;
                    case 11:
                        win(Bet.field, roll);
                        win(Bet.come, roll);
                        break;
                    case 12:
                        win(Bet.field, roll);
                        break;
                    default:
                        break;
                }
            }
            return new Dictionary<Bet,uint>(bets);
        }

        public bool addBet(Bet bet, uint amount)
        {
            if (point == 0)
            {
                // You can bet pass or don't pass, but nothing else
                if (bet == Bet.dontpass || bet == Bet.passline)
                {
                    placeBet(bet, amount);
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                // you can bet everything but pass and don't pass
                if (bet == Bet.dontpass || bet == Bet.passline)
                {
                    return false;
                }
                else
                {
                    placeBet(bet, amount);
                    return true;
                }
            }
        }

        private void placeBet(Bet bet, uint amount)
        {
            if (bets.ContainsKey(bet))
            {
                bets[bet] += amount;
                oldBets[bet] = bets[bet];
            }
            else
            {
                bets[bet] = amount;
                oldBets[bet] = amount;
            }
        }
        public bool removeBet(Bet bet, uint amount)
        {
            // TODO: Add rules for removing bets
            if (bets.ContainsKey(bet))
            {
                if (amount == bets[bet])
                {
                    bets.Remove(bet);
                    oldBets.Remove(bet);
                }
                else
                {
                    bets[bet] -= amount;
                    oldBets[bet] = bets[bet];
                }
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
